summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/ir_opt/constant_propagation_pass.cpp')
-rw-r--r--src/shader_recompiler/ir_opt/constant_propagation_pass.cpp76
1 files changed, 73 insertions, 3 deletions
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
index 826f9a54a..4d81e9336 100644
--- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
+++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp
@@ -7,6 +7,7 @@
#include <type_traits>
#include "common/bit_cast.h"
+#include "shader_recompiler/environment.h"
#include "shader_recompiler/exception.h"
#include "shader_recompiler/frontend/ir/ir_emitter.h"
#include "shader_recompiler/frontend/ir/value.h"
@@ -515,6 +516,9 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) {
case IR::Attribute::PrimitiveId:
case IR::Attribute::InstanceId:
case IR::Attribute::VertexId:
+ case IR::Attribute::BaseVertex:
+ case IR::Attribute::BaseInstance:
+ case IR::Attribute::DrawID:
break;
default:
return;
@@ -644,7 +648,63 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) {
}
}
-void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
+void FoldConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst) {
+ const IR::Value bank{inst.Arg(0)};
+ const IR::Value offset{inst.Arg(1)};
+ if (!bank.IsImmediate() || !offset.IsImmediate()) {
+ return;
+ }
+ const auto bank_value = bank.U32();
+ const auto offset_value = offset.U32();
+ auto replacement = env.GetReplaceConstBuffer(bank_value, offset_value);
+ if (!replacement) {
+ return;
+ }
+ const auto new_attribute = [replacement]() {
+ switch (*replacement) {
+ case ReplaceConstant::BaseInstance:
+ return IR::Attribute::BaseInstance;
+ case ReplaceConstant::BaseVertex:
+ return IR::Attribute::BaseVertex;
+ case ReplaceConstant::DrawID:
+ return IR::Attribute::DrawID;
+ default:
+ throw NotImplementedException("Not implemented replacement variable {}", *replacement);
+ }
+ }();
+ IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
+ if (inst.GetOpcode() == IR::Opcode::GetCbufU32) {
+ inst.ReplaceUsesWith(ir.GetAttributeU32(new_attribute));
+ } else {
+ inst.ReplaceUsesWith(ir.GetAttribute(new_attribute));
+ }
+}
+
+void FoldDriverConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst, u32 which_bank,
+ u32 offset_start = 0, u32 offset_end = std::numeric_limits<u16>::max()) {
+ const IR::Value bank{inst.Arg(0)};
+ const IR::Value offset{inst.Arg(1)};
+ if (!bank.IsImmediate() || !offset.IsImmediate()) {
+ return;
+ }
+ const auto bank_value = bank.U32();
+ if (bank_value != which_bank) {
+ return;
+ }
+ const auto offset_value = offset.U32();
+ if (offset_value < offset_start || offset_value >= offset_end) {
+ return;
+ }
+ IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
+ if (inst.GetOpcode() == IR::Opcode::GetCbufU32) {
+ inst.ReplaceUsesWith(IR::Value{env.ReadCbufValue(bank_value, offset_value)});
+ } else {
+ inst.ReplaceUsesWith(
+ IR::Value{Common::BitCast<f32>(env.ReadCbufValue(bank_value, offset_value))});
+ }
+}
+
+void ConstantPropagation(Environment& env, IR::Block& block, IR::Inst& inst) {
switch (inst.GetOpcode()) {
case IR::Opcode::GetRegister:
return FoldGetRegister(inst);
@@ -789,18 +849,28 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) {
IR::Opcode::CompositeInsertF16x4);
case IR::Opcode::FSwizzleAdd:
return FoldFSwizzleAdd(block, inst);
+ case IR::Opcode::GetCbufF32:
+ case IR::Opcode::GetCbufU32:
+ if (env.HasHLEMacroState()) {
+ FoldConstBuffer(env, block, inst);
+ }
+ if (env.IsPropietaryDriver()) {
+ FoldDriverConstBuffer(env, block, inst, 1);
+ }
+ break;
default:
break;
}
}
+
} // Anonymous namespace
-void ConstantPropagationPass(IR::Program& program) {
+void ConstantPropagationPass(Environment& env, IR::Program& program) {
const auto end{program.post_order_blocks.rend()};
for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) {
IR::Block* const block{*it};
for (IR::Inst& inst : block->Instructions()) {
- ConstantPropagation(*block, inst);
+ ConstantPropagation(env, *block, inst);
}
}
}